import {
	IContext,
	ICtrlActionResult,
	IHttpResponse,
	IParam,
	ITreeAbility,
	ITreeController,
	ITreeControllerParams,
	ITreeModel,
	ITreeStore,
	TreeActionType,
} from '@/core/interface';
import { ControlVOBase } from '@/core/modules';
import TreeService from '@/core/modules/ctrl-service/tree-service';
import { deepCopy } from '@/core/utils';
import { MDCtrlControllerBase } from './md-ctrl-controller-base';

/**
 * 树部件控制器
 *
 * @export
 * @class TreeController
 * @extends {(MDExCtrlController<T | TreeActionType, ITreeStore, ITreeAbility>)}
 * @implements {ITreeController}
 * @template T
 */
export class TreeController
	extends MDCtrlControllerBase<TreeActionType, ITreeStore, ITreeAbility>
	implements ITreeController<ITreeStore, ITreeAbility>
{
	/**
	 * 树部件服务
	 *
	 * @protected
	 * @type {TreeService<ControlVOBase[]>}
	 * @memberof TreeController
	 */
	protected declare ctrlService: TreeService<ControlVOBase[]>;

	/**
	 * 树模型
	 *
	 * @protected
	 * @type {ITreeModel}
	 * @memberof TreeController
	 */
	protected declare readonly model: ITreeModel;

	protected tileData: IParam[] = [];

	/**
	 * 节点过滤
	 *
	 * @private
	 * @type {string}
	 * @memberof TreeController
	 */
	private nodeFilter: string = '';

	/**
	 * Creates an instance of TreeController.
	 * @param {ITreeControllerParams<TreeActionType, ITreeAbility>} params
	 * @memberof TreeController
	 */
	public constructor(
		params: ITreeControllerParams<TreeActionType, ITreeAbility>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {ITreeControllerParams<TreeActionType, ITreeAbility>} params
	 * @memberof TreeController
	 */
	protected processCtrlInit(
		params: ITreeControllerParams<TreeActionType, ITreeAbility>
	) {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			expandedKeys: [],
			selectedKeys: [],
			selections: params.selections,
			initTree: true,
		});
	}

	/**
	 * 加载数据
	 *
	 * @param {IParam} [node={}]
	 * @return {*}  {Promise<ICtrlActionResult>}
	 * @memberof TreeController
	 */
	public async load(node: IParam = {}): Promise<ICtrlActionResult> {
		const params: IParam = {
			srfnodeid: node && node.id ? node.id : '#',
			srfnodefilter: this.nodeFilter,
			parentData: node?.curData,
		};
		const { tempContext, tempViewParams } = this.computeNodeParams(node);
		const parentData: IParam = {};
		this.emit('beforeLoad', [parentData]);
		Object.assign(params, { viewParams: { ...tempViewParams, ...parentData } });
		const isRoot = this.store.data.length == 0;
		if (isRoot) {
			this.beforeAsyncAction('load', tempContext, params);
		}
		try {
			const response: IHttpResponse = await this.ctrlService.getNodes(
				tempContext,
				params
			);
			if (response.success) {
				const data = response.data;
				this.addTileData(data);
				this.tileData.push(...data);
				this.setAppendCaption(data);
				if (isRoot) {
					this.store.data = data;
				} else {
					const nodeData = this.getTreeNodeByKey(node.id);
					data.forEach((item: any) => {
						item.parentNodeId = node.id;
					});
					if (nodeData) {
						if (data && data.length > 0) {
							nodeData.children = data;
						} else {
							nodeData.isLeaf = true;
						}
					}
				}
				this.setDefaultSelection(data, isRoot, node.checked);
				this.emit('load', this.getData());
				if (isRoot) {
					this.afterAsyncAction('load', response);
				}
				return { ok: true, data: this.getData(), rowData: response.data };
			}
			if (isRoot) {
				this.afterAsyncAction('load', response);
			}
			return { ok: false, data: this.getData(), rowData: response.data };
		} catch (error: any) {
			if (isRoot) {
				this.afterAsyncAction('load', error);
			}
			return { ok: false, data: this.getData(), rowData: error };
		}
	}

	private addTileData(items: IParam[]) {
		items.forEach((item: IParam) => {
			if (
				this.tileData.findIndex((td: IParam) => td.srfkey !== item.srfkey) ===
				-1
			) {
				this.tileData.push(item);
			}
		});
	}

	/**
	 * 处理值改变
	 *
	 * @param {IParam} node
	 * @memberof TreeController
	 */
	public handleValueChange(node: IParam) {}

	/**
	 * 刷新所有节点
	 *
	 * @memberof TreeController
	 */
	public async refreshAllNode(opt?: IParam): Promise<ICtrlActionResult> {
		this.store.data = [];
		this.store.initTree = false;
		if (opt?.query) {
			this.nodeFilter = opt.query;
		} else {
			this.nodeFilter = '';
		}
		setTimeout(async () => {
			this.store.initTree = true;
		}, 0);
		return await this.load();
	}

	/**
	 * 刷新父节点
	 *
	 * @memberof TreeController
	 */
	public async refreshParentNode() {
		if (this.store.selections.length > 0) {
			const curNode = this.store.selections[0];
			const parentNodeId = curNode.parentNodeId;
			if (parentNodeId) {
				const { tempContext, tempViewParams } = this.computeNodeParams(curNode);
				const param = {
					srfnodeid: parentNodeId,
					viewParams: tempViewParams,
				};
				await this.refreshNode(tempContext, param);
			} else {
				await this.refreshAllNode();
			}
		}
	}

	/**
	 * 刷新当前节点
	 *
	 * @memberof TreeController
	 */
	public refreshCurrentNode() {
		if (this.store.selections.length > 0) {
			const curNode = this.store.selections[0];
			const curNodeId = curNode.id;
			const { tempContext, tempViewParams } = this.computeNodeParams(curNode);
			const param = {
				srfnodeid: curNodeId,
				viewParams: tempViewParams,
			};
			this.refreshNode(tempContext, param);
		}
	}

	/**
	 * 刷新节点
	 *
	 * @param {string} context 上下文
	 * @param {IContext} params 参数
	 * @memberof TreeController
	 */
	private async refreshNode(context: IContext, params: IParam) {
		try {
			this.beforeAsyncAction('load', context, params);
			const response: IHttpResponse = await this.ctrlService.getNodes(
				context,
				params
			);
			if (response.success) {
				const data = response.data;
				this.setAppendCaption(data);
				const nodeData = this.getTreeNodeByKey(params.srfnodeid);
				data.forEach((item: any) => {
					item.parentNodeId = params.srfnodeid;
				});
				if (nodeData) {
					nodeData.children = data;
				}
				this.setDefaultSelection(data, false, nodeData.selected);
				this.emit('load', this.getData());
				this.afterAsyncAction('load', response);
				return { ok: true, data: this.getData(), rowData: response.data };
			}
			this.afterAsyncAction('load', response);
			return { ok: false, data: this.getData(), rowData: response.data };
		} catch (error: any) {
			this.afterAsyncAction('load', error);
			return { ok: false, data: this.getData(), rowData: error };
		}
	}

	/**
	 * 处理选中数据改变
	 *
	 * @param {IParam[]} selections
	 * @memberof TreeController
	 */
	public handleSelectionChange(selections: IParam[]) {
		this.store.selections = selections;
		const selectedKeys: string[] = [];
		selections.forEach((selection) => {
			selectedKeys.push(selection.id);
		});
		this.store.selectedKeys = selectedKeys;
		this.emit('selectionChange', this.getData());
	}

	/**
	 * 设置默认选中
	 *
	 * @private
	 * @param {IParam[]} items
	 * @param {boolean} [isRoot=false]
	 * @param {boolean} [isSelectedAll=false]
	 * @return {*}  {void}
	 * @memberof TreeController
	 */
	private setDefaultSelection(
		items: IParam[],
		isRoot = false,
		isSelectedAll = false
	): void {
		if (items.length === 0) {
			return;
		}
		const { viewParams } = this.store;
		//  导航视图中选中优先级高于其他
		if (this.selectFirstDefault) {
			let index = 0;
			if (isRoot) {
				if (viewParams && viewParams.srfnavtag) {
					const activate = viewParams.srfnavtag;
					index = items.findIndex((item: any) => {
						return (
							item.id && item.id.split(';') && item.id.split(';')[0] == activate
						);
					});
					if (index === -1) index = 0;
				} else {
					index = 0;
				}
			} else {
				return;
			}
			this.store.selectedKeys = [items[index].id];
			this.store.selections = [items[index]];
			this.emit('selectionChange', this.getData());
			return;
		}
		//  存在选中数据，以选中数据优先
		if (
			viewParams &&
			viewParams.selectedData &&
			viewParams.selectedData.length > 0
		) {
			const selections: IParam[] = [];
			viewParams.selectedData.forEach((select: IParam) => {
				if (select.srfkey) {
					const item = this.tileData.find(
						(i: IParam) => i.srfkey === select.srfkey
					);
					if (item) {
						selections.push(item);
					}
				}
			});
			if (selections.length > 0) {
				this.handleSelectionChange(selections);
				return;
			}
		}
		// 如果父节点选中则选中所有子节点
		const defaultSelect = isSelectedAll
			? items
			: items.filter((item: any) => item.selected);
		const selections: IParam[] = [];
		selections.push(...this.store.selections);
		if (this.singleSelect) {
			if (selections.length == 0 && defaultSelect.length > 0) {
				selections.push(defaultSelect[0]);
			}
		} else {
			defaultSelect.forEach((select: IParam) => {
				const index = selections.findIndex(
					(selected: IParam) => select.id === selected.id
				);
				if (index === -1) {
					selections.push(select);
				}
			});
		}
		selections.forEach((selectNode: IParam) => {
			this.store.selectedKeys.push(selectNode.id);
		});
		this.emit('selectionChange', this.getData());
	}

	/**
	 * 设置附加标题
	 *
	 * @private
	 * @param {IParam[]} items
	 * @memberof TreeController
	 */
	private setAppendCaption(items: IParam[]) {
		items.forEach((item: IParam) => {
			if (item.appendCaption && item.textFormat) {
				item.text = item.textFormat + item.text;
			}
		});
	}

	/**
	 * 计算节点参数
	 *
	 * @private
	 * @param {IParam} curNode
	 * @return {*}  {{ tempContext: IParam, tempViewParams: IParam }}
	 * @memberof TreeController
	 */
	private computeNodeParams(curNode: IParam): {
		tempContext: IParam;
		tempViewParams: IParam;
	} {
		const { context, viewParams } = this.store;
		let tempContext: IParam = {};
		const tempViewParams: any = deepCopy(viewParams);
		if (curNode && curNode.srfappctx) {
			tempContext = deepCopy(curNode.srfappctx);
		} else {
			tempContext = deepCopy(context);
		}
		if (curNode) {
			if (curNode.srfparentdename) {
				Object.assign(tempContext, {
					srfparentdename: curNode.srfparentdename,
				});
				Object.assign(tempViewParams, {
					srfparentdename: curNode.srfparentdename,
				});
			}
			if (curNode.srfparentdemapname) {
				Object.assign(tempContext, {
					srfparentdemapname: curNode.srfparentdemapname,
				});
				Object.assign(tempViewParams, {
					srfparentdemapname: curNode.srfparentdemapname,
				});
			}
			if (curNode.srfparentkey) {
				Object.assign(tempContext, { srfparentkey: curNode.srfparentkey });
				Object.assign(tempViewParams, { srfparentkey: curNode.srfparentkey });
			}
		}
		return { tempContext, tempViewParams };
	}

	/**
	 * 根据节点标识获取父节点
	 *
	 * @private
	 * @param {string} id
	 * @param {string} [key='id']
	 * @return {*}  {*}
	 * @memberof TreeController
	 */
	private getTreeNodeByKey(id: string, key = 'id'): any {
		const { data } = this.store;
		let node = null;
		if (data.length > 0 && id) {
			const getNode = (item: any): boolean => {
				let flag = false;
				if (item[key] === id) {
					node = item;
					flag = true;
				}
				if (item.children && item.children.length > 0) {
					for (const child of item.children) {
						if (getNode(child)) {
							flag = true;
							break;
						}
					}
				}
				return flag;
			};
			for (const item of data) {
				if (getNode(item)) {
					break;
				}
			}
		}
		return node;
	}

	/**
	 * 获取能力
	 *
	 * @return {*}  {ITreeAbility}
	 * @memberof TreeController
	 */
	public getAbility(): ITreeAbility {
		return {
			...super.getAbility(),
			refreshAllNode: this.refreshAllNode.bind(this),
			refreshParentNode: this.refreshParentNode.bind(this),
			refreshCurrentNode: this.refreshCurrentNode.bind(this),
		};
	}
}
